﻿using EventMgrLib;
using IniReadWrite;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using VisionRoc.Tool;

namespace VisionRoc.Core
{
    /// <summary>
    /// 普通串口通信
    /// </summary>
    public class SerialPortTool
    {
        
        /// <summary>
        /// 声明串口对象
        /// </summary>
        public SerialPort serialPort;

        /// <summary>
        /// 串口数据保存路径
        /// </summary>
        string SerialPortPath = string.Empty;
        public SerialPortTool(string _Path)
        {
            serialPort = new SerialPort();
            if (!Directory.Exists(_Path))
            {
                Directory.CreateDirectory(_Path);
            }
            SerialPortPath = _Path + "\\SerialPort.ini";
         
            if (File.Exists(SerialPortPath))
            {
                ReadParameter();
                OpenSerialPore();
            }
        }

        /// <summary>
        /// 串口打开状态
        /// </summary>
        public bool IsOpenState = false;

        /// <summary>
        /// 串口号
        /// </summary>
        public string Port = string.Empty;

        /// <summary>
        /// 波特率
        /// </summary>
        public int Baud;

        /// <summary>
        /// 校验位
        /// </summary>
        public string Parity = string.Empty;

        /// <summary>
        /// 数据位
        /// </summary>
        public int DataBits;

        /// <summary>
        /// 停止位
        /// </summary>
        public string StopBits = string.Empty;

        /// <summary>
        /// DTS   1为设置 2位取消
        /// </summary>
        public int RTS = 2;

        /// <summary>  
        /// DTR   1为设置 2为取消
        /// </summary>
        public int DTR = 2;

        /// <summary>
        /// 是否设置读取16进制  1为设置  2为取消设置
        /// </summary>
        public int IsRaed16Hex = 2;

        /// <summary>
        /// 是否设置发送16进制  1为设置  2位取消设置
        /// </summary>
        public int IsSend16Hex = 2;

        /// <summary>
        /// 串口接收信息
        /// </summary>
        string Message = string.Empty;

        /// <summary>
        /// 初始化串口信息
        /// </summary>
        /// <param name="cmb_Port">初始化串口号信息控件</param>
        /// <param name="cmb_Baud">初始化波特率信息控件</param>
        /// <param name="cmb_Parity">初始化校验位信息控件</param>
        /// <param name="cmb_StopBits">初始化停止位信息控件</param>
        /// <param name="cmb_DataBits">初始化数据位信息控件</param>
        public void IniSerialPortInfo(ComboBox cmb_Port, ComboBox cmb_Baud, ComboBox cmb_Parity, ComboBox cmb_StopBits, ComboBox cmb_DataBits)
        {
            //获取通信端口号   
            string[] PortList = SerialPort.GetPortNames();
            if (PortList.Length > 0)
            {
                cmb_Port.DataSource = PortList;
                cmb_Port.SelectedIndex = 0;
            }
            // 波特率
            string[] BaudList = new string[]    { "2400", "4800", "9600", "19200", "28400", "115200" };
            cmb_Baud.DataSource = BaudList;
            cmb_Baud.SelectedIndex = 2;

            // 校验位
            cmb_Parity.DataSource = Enum.GetNames(typeof(Parity));
            cmb_Parity.SelectedIndex = 0;

            //停止位
            cmb_StopBits.DataSource = Enum.GetNames(typeof(StopBits));
            cmb_StopBits.SelectedIndex = 1;

            //数据位
            int[] DataList = new int[] { 5, 6, 7, 8 };
            cmb_DataBits.DataSource = DataList;
            cmb_DataBits.SelectedIndex = 3;

        }

        /// <summary>
        /// 打开串口
        /// </summary>
        public void OpenSerialPore()
        {
            try
            {
                serialPort.PortName = Port;
                serialPort.BaudRate = Baud;
                serialPort.Parity = (Parity)Enum.Parse(typeof(Parity), Parity, true);
                serialPort.DataBits = DataBits;
                serialPort.StopBits = (StopBits)Enum.Parse(typeof(StopBits), StopBits, true);

                if (RTS == 1) { serialPort.RtsEnable = true; } else { serialPort.RtsEnable = false; }
                if (DTR == 1) { serialPort.DtrEnable = true; } else { serialPort.DtrEnable = false; }

                serialPort.ReceivedBytesThreshold = 1;  //接收到一个字节就触发  当值等于100  接收100字节才出发
                //serialPort.DataReceived += M_SerialPort_DataReceived;    // 接收字节的的事件
                if (serialPort.IsOpen)
                {
                    serialPort.Close();
                }

                serialPort.Open();
                IsOpenState = true;
                Global.AddLogInfoEvent(LogLevel.OK, $"串口打开成功！串口信息：串口号：{Port},波特率：{Baud.ToString()},校验位：{Parity},数据位：{DataBits.ToString()},停止位：{StopBits}");
            }
            catch
            {
                IsOpenState = false;
                Global.AddLogInfoEvent(LogLevel.Error, $"串口打开失败！串口信息：串口号：{Port},波特率：{Baud.ToString()},校验位：{Parity},数据位：{DataBits.ToString()},停止位：{StopBits}");
            }
        }

        /// <summary>
        /// 关闭串口
        /// </summary>
        public void CloseSerialPore()
        {
            ///判断串口对象是不是为 NULL 
            if (serialPort != null)
            {
                //判断串口打开状态是不是为 TRUE
                if (IsOpenState)
                {
                    //判断串口是否打开
                    if (serialPort.IsOpen)
                    {
                        serialPort.Close();  // 串口如果打开则关闭
                        IsOpenState = false; // 将串口状态设置为false
                    }
                }
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        public void SendData(string Message)
        {
            try
            {
                //判断是否为16进制发送
                if (IsSend16Hex == 1)
                {
                    //string HexStr = HexHelper.StringToHexString(Message, Encoding.Default);
                    //byte[] byteArray = System.Text.Encoding.Default.GetBytes(HexStr);

                    byte[] byteArray = HexHelper.strToHexByte(Message);
                    serialPort.Write(byteArray, 0, byteArray.Length);
                }
                else if (IsSend16Hex == 2)
                {
                    byte[] b = Encoding.Default.GetBytes(Message);
                    serialPort.Write(b, 0, b.Length);
                }
            }
            catch
            {

            }
        }

        public string GetHexFromChs(string s)
        {
            if ((s.Length % 2) != 0)
            {
                s += " ";//空格
                         //throw new ArgumentException("s is not valid chinese string!");
            }

            System.Text.Encoding chs = System.Text.Encoding.GetEncoding("gb2312");

            byte[] bytes = chs.GetBytes(s);

            string str = "";

            for (int i = 0; i < bytes.Length; i++)
            {
                str += string.Format("{0:X}", bytes[i]);
            }

            return str;
        }

        /// <summary>
        /// 字符串转16进制字节
        /// </summary>
        /// <param name="hexString"></param>
        /// <returns></returns>
        public byte[] strToHexByte(string hexString)
        {
            hexString = hexString.Replace(" ", "");
            if ((hexString.Length % 2) != 0)
            {
                hexString += " ";
            }
            byte[] returnBytes = new byte[hexString.Length / 2];
            for (int i = 0; i < returnBytes.Length; i++)
            {
                returnBytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2).Replace(" ", ""), 16);
            }

            return returnBytes;
        }

        /// <summary>
        /// 串口接收信息事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void M_SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            Message = string.Empty;
            if (IsRaed16Hex == 1)
            {
                byte[] data = new byte[serialPort.BytesToRead];
                serialPort.Read(data, 0, data.Length);
                foreach (byte item in data)
                {
                    string hex = Convert.ToString(item, 16).ToUpper();
                    Message += (hex.Length == 1 ? "0" + hex : hex) + " ";
                }
                // 发布日志事件
                EventMgr.Ins.GetEvent<SerialPortInfo>().Publish(new SerialPortMessage()
                {
                    SolutionName = "Main",
                    Msg = Message
                });
            }
            else
            {
                serialPort.Encoding = Encoding.Default;
                Message = serialPort.ReadExisting();
                // 发布日志事件
                EventMgr.Ins.GetEvent<SerialPortInfo>().Publish(new SerialPortMessage()
                {
                    SolutionName = "Main",
                    Msg = Message
                });
            }
        }

        /// <summary>
        /// 读取参数
        /// </summary>
        public void ReadParameter()
        {
            try
            {
                Port = IniAPI.INIGetStringValue(SerialPortPath, "SerialPortParameter", "COM", "0");
                Baud = Convert.ToInt32(IniAPI.INIGetStringValue(SerialPortPath, "SerialPortParameter", "Baud", "0"));
                Parity = IniAPI.INIGetStringValue(SerialPortPath, "SerialPortParameter", "Parity", "0");
                DataBits = Convert.ToInt32(IniAPI.INIGetStringValue(SerialPortPath, "SerialPortParameter", "DataBits", "0"));
                StopBits = IniAPI.INIGetStringValue(SerialPortPath, "SerialPortParameter", "StopBits", "0");
                RTS = Convert.ToInt32(IniAPI.INIGetStringValue(SerialPortPath, "SerialPortParameter", "RTS", "0"));
                DTR = Convert.ToInt32(IniAPI.INIGetStringValue(SerialPortPath, "SerialPortParameter", "DTR", "0"));
                IsRaed16Hex = Convert.ToInt32(IniAPI.INIGetStringValue(SerialPortPath, "SerialPortParameter", "IsRaed16Hex", "0"));
                IsSend16Hex = Convert.ToInt32(IniAPI.INIGetStringValue(SerialPortPath, "SerialPortParameter", "IsSend16Hex", "0"));
            }
            catch
            {

            }
        }

        /// <summary>
        /// 保存参数
        /// </summary>
        public void WriteParameter()
        {
            IniAPI.INIWriteValue(SerialPortPath, "SerialPortParameter", "COM", Port.ToString());
            IniAPI.INIWriteValue(SerialPortPath, "SerialPortParameter", "Baud", Baud.ToString());
            IniAPI.INIWriteValue(SerialPortPath, "SerialPortParameter", "Parity", Parity.ToString());
            IniAPI.INIWriteValue(SerialPortPath, "SerialPortParameter", "DataBits", DataBits.ToString());
            IniAPI.INIWriteValue(SerialPortPath, "SerialPortParameter", "StopBits", StopBits.ToString());
            IniAPI.INIWriteValue(SerialPortPath, "SerialPortParameter", "RTS", RTS.ToString());
            IniAPI.INIWriteValue(SerialPortPath, "SerialPortParameter", "DTR", DTR.ToString());
            IniAPI.INIWriteValue(SerialPortPath, "SerialPortParameter", "IsRaed16Hex", IsRaed16Hex.ToString());
            IniAPI.INIWriteValue(SerialPortPath, "SerialPortParameter", "IsSend16Hex", IsSend16Hex.ToString());
        }

        ~SerialPortTool()
        {
            CloseSerialPore();
        }

    }
}
